#ifndef TRANSFORMERCONTENTPORTSTREAMOUT_HPP_3
#define TRANSFORMERCONTENTPORTSTREAMOUT_HPP_3

#include "logger.hpp"
#include "transContentDefine.h"
#include "transContentDispatcher.hpp"
#include "transContentErrorCode.h"

class TransStreamOutMemory : public TransContentITimerEvent{
private:
	int mCapacity;
	int mAckStartIndex;
	int mAckStartFragmentId;
	int mLeftCount;
	int mInsertIndex;
	int timeout;
	int mElapseTimeFromLast;
	short* mRecordBuffer;
	pthread_mutex_t waitMutex;
	pthread_cond_t waitCond;
	pthread_mutex_t accessPoolMutex;
	sendSyncCallback sscb;
	char* mOutData;
	int mOutDataLen;
	int mOutStreamValue;
	int remotePort;
	NodeAddr target;
	int shouldSendCount;
	int allowSendCount;
	int startSendIndex;
	/// stream port instance get this value to send a port heartbeat
	int checkRemoteHeartBeat;
	/// when timeout, or user cancel the send thread
	int sending;
	/// the send data thread working flag
	int working;
	pthread_t workPid;
	pthread_mutex_t dataAvalaMutex;
		pthread_cond_t dataAvalaCond;
public:
	TransStreamOutMemory(): mCapacity(PACKET_BUFFER_SIZE_DEFAULT), mAckStartIndex(0), mAckStartFragmentId(0), mLeftCount(mCapacity), mInsertIndex(0), timeout(INT_MAX), mElapseTimeFromLast(0), mRecordBuffer(NULL), waitMutex(PTHREAD_MUTEX_INITIALIZER), waitCond(PTHREAD_COND_INITIALIZER), accessPoolMutex(PTHREAD_MUTEX_INITIALIZER), sscb(NULL), mOutData(NULL), mOutDataLen(0){
		debug_enter();
		logd_info("stream out memory consructor, construct the out buffer and set the values to -1");
		mRecordBuffer = (short*)calloc(mCapacity, sizeof(short));
		for(int i=0; i< mCapacity; ++i){
			mRecordBuffer[i] = -1;
		}
	
		mOutStreamValue = 0;
		remotePort = 0;
		shouldSendCount = 0;
		allowSendCount = mCapacity;
		startSendIndex = 0;
		checkRemoteHeartBeat = 0;
		sending = 0;
		working = 1;
		dataAvalaMutex = PTHREAD_MUTEX_INITIALIZER;
		dataAvalaCond = PTHREAD_COND_INITIALIZER;
		pthread_create(&workPid, NULL, sendDataRoute, this);
		pthread_detach(&workPid);
		debug_leave();
	}

	~TransStreamOutMemory(){
		if(mRecordBuffer != NULL){
			free(mRecordBuffer);
			mRecordBuffer = NULL;
		}
		working = 0;
		pthread_cancel(workPid);
	}

	int getCapacity()const {
		return mCapacity;
	}
	int getLeftSpaceBytes()const {
		return mLeftCount * (TransContentSetting::getMemoryBufferSize() - 50);
	}
	
	int getTimeout() const {
		return this->timeout;
	}
	void setTimeout(int timeout){
		this->timeout = timeout;
	}
	
	int send(int flag, const void* buffer, int bufferLen, int timeout, sendSyncCallback sscb);
	
	void OnTimer();


	int response(char* buffer, int index);

private:
	int sendFinished();
	static void* finishRoute(void *p){
		(TransStreamOutMemory*(p))->finishCallback();
	}
	void finishCallback();
	static void* sendDataRoute(void* p){
		(TransStreamOutMemory*(p))->sendworker();
	}
};
#endif //TRANSFORMERCONTENTPORTSTREAMOUT_HPP_3
